/**
 * @file delay.c
 * @brief 延迟函数实现（基于DWT和HAL库，兼容FreeRTOS）
 */

#include "delay.h"
#include "stm32f1xx_hal.h"

// DWT（Data Watchpoint and Trace）寄存器定义
#define DWT_CTRL    (*(volatile uint32_t *)0xE0001000)  // DWT 控制寄存器
#define DWT_CYCCNT  (*(volatile uint32_t *)0xE0001004)  // DWT 周期计数器
#define DEM_CR      (*(volatile uint32_t *)0xE000EDFC)  // CoreDebug DEMCR 寄存器

#define DWT_CR_CYCCNTENA_Msk  (1UL << 0)    // 使能周期计数器
#define DEM_CR_TRCENA_Msk     (1UL << 24)   // 使能 DWT 和 ITM

// 外部变量声明
extern uint32_t SystemCoreClock;  // 系统时钟频率（定义在 system_stm32f1xx.c）

static uint8_t dwt_initialized = 0;

/**
 * @brief 初始化DWT计数器
 * @note 可以在main函数中显式调用，也可以不调用（delay_us会自动初始化）
 */
void DWT_Init(void)
{
    if (!dwt_initialized)
    {
        DEM_CR |= DEM_CR_TRCENA_Msk;      // 使能 DWT 和 ITM
        DWT_CYCCNT = 0;                    // 清零周期计数器
        DWT_CTRL |= DWT_CR_CYCCNTENA_Msk; // 使能周期计数器
        dwt_initialized = 1;
    }
}

/**
 * @brief 微秒延迟函数（使用DWT，不依赖SysTick）
 * @param us 延迟时间（微秒）
 * @note 使用DWT周期计数器，不受FreeRTOS影响，适合在任何上下文中使用
 */
void delay_us(uint32_t us)
{
    uint32_t start_tick, current_tick;
    uint32_t ticks_to_wait;
    
    DWT_Init();  // 确保DWT已初始化
    
    ticks_to_wait = us * (SystemCoreClock / 1000000);  // 需要的CPU周期数
    start_tick = DWT_CYCCNT;                           // 记录开始时的计数值
    
    // 等待足够的CPU周期
    do {
        current_tick = DWT_CYCCNT;
    } while ((current_tick - start_tick) < ticks_to_wait);
}

/**
 * @brief 毫秒延迟函数（短延时用DWT，长延时用HAL_Delay）
 * @param ms 延迟时间（毫秒）
 * @note 在FreeRTOS任务中使用长延时时，建议使用osDelay()而不是delay_ms()
 */
void delay_ms(uint32_t ms)
{

        delay_us(ms * 1000);

}
